package org.auth.service;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.binary.StringUtils;
import org.auth.bean.CustomUserDetails;
import org.auth.cache.bean.VerificationCode;
import org.auth.domain.mapper.UserBaseMapper;
import org.auth.domain.model.UserBase;
import org.auth.framework.CustomUserDetailsService;
import org.auth.type.AuthenticationType;
import org.auth.type.ClientType;
import org.auth.type.DelType;
import org.auth.type.RoleType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;


@Service
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
	/**
	 * 用户Mapper
	 */
	@Autowired
	private UserBaseMapper userMapper;
	
	/**
	 * 验证码服务
	 */
	@Autowired
	private BaseVerificationCodeService verificationCodeService;
	
	/**
	 * 密码生成器
	 */
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	/**
	 * 取得用户情报
	 * 
	 * @param username 用户名
	 * @return 用户情况
	 */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {	
    	UserBase result = userMapper.selectByPrimaryKey(Long.valueOf(username));
		Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
		authorities.add(new SimpleGrantedAuthority("ROLE_" + RoleType.getEnumByCode(result.getRoleId()).toString()));
		return new CustomUserDetails(result, authorities);
    }
    
    /**
	 * 取得用户情报
	 * 
	 * @param username 用户名
	 * @param authentication 授权信息
	 * @return 用户情况
	 */
    @Override
    public UserDetails loadUserByUsername(String username, UsernamePasswordAuthenticationToken authentication) throws UsernameNotFoundException {
    	
    	Map<String, String> parameters = new HashMap<String,String>();
		if(authentication.getDetails() instanceof Map) {
			parameters = (Map<String, String>)authentication.getDetails();
		}
		
    	AuthenticationType authenticationType = AuthenticationType.valueOf(parameters.get(AuthenticationType.class.getSimpleName()));
    	ClientType clientType = ClientType.valueOf(parameters.get("client_id"));
    	
    	if(AuthenticationType.IDENTIFYING.equals(authenticationType) && clientType != ClientType.zhshWEB) {
    		VerificationCode verificationCode= verificationCodeService.getVerificationCode(username, clientType.toString());
    		UserBase record = new UserBase();
			record.setLoginId(username);
			record.setClientId(clientType.getCode());
			UserBase result = userMapper.selectOne(record);
			
    		if(verificationCodeService.chkVerificationCode(username, clientType.toString(), authentication.getCredentials().toString()) && clientType == ClientType.zhshAPP && result == null) {
    			record.setRoleId(RoleType.NORMAL.getCode());
    			record.setDelFlg(DelType.ENABLE.getCode());
				int count = userMapper.insert(record);
				if(count != 1) {
					throw new UsernameNotFoundException(username + " is not found.");
				}
				result = record;
    		}
			if (result != null) {
				result.setPassword(verificationCode.getVerificationCode());
				Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
				authorities
						.add(new SimpleGrantedAuthority("ROLE_" + RoleType.getEnumByCode(result.getRoleId()).toString()));
				return new CustomUserDetails(result, authorities);
			}
		} else if (AuthenticationType.PASSWORD.equals(authenticationType) && clientType != ClientType.zhshWX) {
			UserBase record = new UserBase();
			record.setLoginId(username);
			record.setClientId((long) clientType.getCode());
			UserBase result = userMapper.selectOne(record);
			Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
			authorities.add(new SimpleGrantedAuthority("ROLE_" + RoleType.getEnumByCode(result.getRoleId()).toString()));
			return new CustomUserDetails(result, authorities);
		}
        throw new UsernameNotFoundException(username + " is not found.");
    }
    
    /**
	 * 是否授权
	 * 
	 * @param userDetails 用户信息
	 * @param authentication 授权信息
	 * @return 授权状态
	 */
	public boolean isAuthentication(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) {
		Map<String, String> parameters = new HashMap<String,String>();
		if(authentication.getDetails() instanceof Map) {
			parameters = (Map<String, String>)authentication.getDetails();
		}
		
		AuthenticationType authenticationType = AuthenticationType.valueOf(parameters.get(AuthenticationType.class.getSimpleName()));
    	
    	String presentedPassword = authentication.getCredentials().toString();
    	
    	if(AuthenticationType.IDENTIFYING.equals(authenticationType)) {
    		return StringUtils.equals(presentedPassword, userDetails.getPassword());
    	} else {
    		return passwordEncoder.matches(presentedPassword, userDetails.getPassword());
    	}
	}
	
	/**
	 * 认证后处理
	 * 
	 * @param principal 认证
	 * @param authentication 授权信息
	 * @param user 用户
	 */
	public void postExecute(Object principal,
			Authentication authentication, UserDetails user) {
		// 本系统不使用
	}
}
